import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

public class MyPanel extends JPanel implements KeyListener, Runnable {
    HeroTank hero = new HeroTank(0, 0);
    int enemyTankSize = Constant.ENEMY_TANK_NUM;//生成敌方数量
    Vector<EnemyTank> enemyTanks = new Vector<>();
    Vector<Bomb> bombs = new Vector<>();

    boolean beginFlag = false;

    public MyPanel() {//进行对象的初始化

    }

    public void begin() {
        beginFlag = true;
        hero = new HeroTank(100, 100);
        for (int i = 0; i < enemyTankSize; i++) {
            EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 100);//坦克绘制
            enemyTanks.add(enemyTank);//坦克纳入集合管理
            enemyTank.setDirect((int) (Math.random() * 4));//方向
            new Thread(enemyTank).start();//启动线程
            Shot shot = new Shot(enemyTank.getX() - 2, enemyTank.getY() + 30, enemyTank.getDirect());//子弹绘制
            enemyTank.Shots.add(shot);//子弹纳入集合管理
            new Thread(shot).start();//子弹线程启动
        }
    }

    public void refreshGame() {
        enemyTanks = new Vector<>();
        bombs = new Vector<>();
        hero = new HeroTank(0, 0);
    }

    public void paint(Graphics g) {//对所有存活对象的绘画方法
        super.paint(g);
        if (beginFlag) {
            g.fillRect(0, 0, Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
            showInfo(g);
            /**
             * 画玩家自己
             */
            if (hero.isLive) {
                drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);
                for (int i = 0; i < hero.Shots.size(); i++) {
                    Shot shot = hero.Shots.get(i);
                    if (shot != null && shot.isLive) {
                        g.fill3DRect(shot.x, shot.y, Constant.BULLET_SIZE, Constant.BULLET_SIZE, false);
                    } else //失效的子弹对象去除
                        hero.Shots.remove(shot);
                }
            }
            /**
             * 画敌对坦克
             */
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                if (enemyTank.isLive) {//活着的就画
                    drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
                    for (int j = 0; j < enemyTank.Shots.size(); j++) {//画子弹
                        Shot shot = enemyTank.Shots.get(j);
                        if (shot.isLive) {
                            g.fill3DRect(shot.x, shot.y, Constant.BULLET_SIZE, Constant.BULLET_SIZE, false);
                        } else {//出界移除
                            enemyTank.Shots.remove(shot);
                        }
                    }
                }
            }
            /**
             * 绘制爆炸动画
             */
            for (int i = 0; i < bombs.size(); i++) {
                Bomb bomb = bombs.get(i);
                if (bomb.lifeDown() > 6) {//实质上是画了几个椭圆
                    g.fillOval(bomb.x - 15, bomb.y - 15, 30, 30);
                    g.fillOval(bomb.x + 10, bomb.y + 10, 20, 20);
                    g.fillOval(bomb.x - 10, bomb.y + 10, 15, 15);
                } else if (bomb.lifeDown() > 3) {
                    g.fillOval(bomb.x - 15, bomb.y - 15, 20, 20);
                    g.fillOval(bomb.x + 5, bomb.y + 5, 40, 40);
                } else {
                    g.fillOval(bomb.x - 10, bomb.y - 10, 20, 20);
                    g.fillOval(bomb.x + 10, bomb.y + 10, 20, 20);
                }
                if (bomb.lifeDown() == 0) {
                    bombs.remove(bomb);
                }
            }
        } else {
            g.fillRect(0, 0, Constant.WINDOW_WIDTH, Constant.WINDOW_HEIGHT);
            g.setColor(Color.ORANGE);
            Font fontTitle = new Font("", Font.BOLD, 100);
            Font fontGuide = new Font("", Font.PLAIN, 20);//设置字体样式
            g.setFont(fontTitle);
            g.drawString("TANK FIGHT", (int) (Constant.GAME_WIDTH * 0.3), (int) (Constant.GAME_HEIGHT * 0.3));
            g.setFont(fontGuide);
            g.drawString("***press SPACE to start***", (int) (Constant.GAME_WIDTH * 0.45), 500);
        }
    }

    /**
     * 右边信息栏的绘制
     */
    public void showInfo(Graphics g) {
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("累计击毁坦克", (int) (Constant.GAME_WIDTH + Constant.GAME_WIDTH * 0.02), 30);
        g.drawString(Recorder.getAllKilledEnemyTankNum() + "", (int) (Constant.GAME_WIDTH + Constant.GAME_WIDTH * 0.11), 90);
        drawTank((int) (Constant.GAME_WIDTH + Constant.GAME_WIDTH * 0.05), 80, g, 0, 1);
    }

    public void drawTank(int x, int y, Graphics g, int direct, int type) {
        switch (type) {
            case 0://playerType
                g.setColor(Color.gray);
                break;
            case 1:
                g.setColor(Color.orange);
                break;
            default:
                break;
        }
        switch (direct) {
            case 0://up
                g.fill3DRect(x - 25, y - 30, 15, 60, false);//leftFoot
                g.fill3DRect(x - 2, y - 30, 4, 30, false);//tube
                g.fill3DRect(x - 10, y - 15, 20, 30, false);//
                g.fill3DRect(x + 10, y - 30, 15, 60, false);//rightFoot
                g.fillOval(x - 8, y - 8, 16, 16);
                break;
            case 1://right
                g.fill3DRect(x - 30, y - 25, 60, 15, false);//
                g.fill3DRect(x, y - 2, 30, 4, false);//tube
                g.fill3DRect(x - 15, y - 10, 30, 20, false);//
                g.fill3DRect(x - 30, y + 10, 60, 15, false);//
                g.fillOval(x - 8, y - 8, 16, 16);
                break;
            case 2://down
                g.fill3DRect(x - 25, y - 30, 15, 60, false);//leftFoot
                g.fill3DRect(x - 2, y, 4, 30, false);//tube
                g.fill3DRect(x - 10, y - 15, 20, 30, false);//
                g.fill3DRect(x + 10, y - 30, 15, 60, false);//rightFoot
                g.fillOval(x - 8, y - 8, 16, 16);
                break;
            case 3://zuo
                g.fill3DRect(x - 30, y - 25, 60, 15, false);//
                g.fill3DRect(x - 30, y - 2, 30, 4, false);//tube
                g.fill3DRect(x - 15, y - 10, 30, 20, false);//
                g.fill3DRect(x - 30, y + 10, 60, 15, false);//
                g.fillOval(x - 8, y - 8, 16, 16);
                break;
            default:
                break;
        }
    }

    /**
     * 该方法只用于检测场上所有物体是否发生碰撞，如果发生碰撞就增加计数器
     * 对对象的删除操作由调用这个方法的方法进行
     * @param s
     * @param enemyTank
     * @return
     */
    public boolean hitTank(Shot s, Tank enemyTank) {
        switch (enemyTank.getDirect()) {//击中时会发生1.坦克对象的消失（以及子弹） 2.炸弹对象的生成
            case 0:
            case 2:
                if (s.x > enemyTank.getX() - 25 && s.x < enemyTank.getX() + 25 && s.y > enemyTank.getY() - 30 && s.y < enemyTank.getY() + 30) {
                    s.isLive = false;
                    enemyTank.isLive = false;
                    enemyTanks.remove(enemyTank);
                    if (enemyTank instanceof EnemyTank)
                        Recorder.addAllKilledEnemyTankNum();
                    Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());
                    bombs.add(bomb);
                    return true;
                }
                break;
            case 1:
            case 3:
                if (s.x > enemyTank.getX() - 30 && s.x < enemyTank.getX() + 30 && s.y > enemyTank.getY() - 25 && s.y < enemyTank.getY() + 25) {
                    s.isLive = false;
                    enemyTank.isLive = false;
                    enemyTanks.remove(enemyTank);
                    if (enemyTank instanceof EnemyTank)
                        Recorder.addAllKilledEnemyTankNum();
                    Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());
                    bombs.add(bomb);
                    return true;
                }
                break;
            default:
                break;
        }
        return false;
    }

    public void hitEnemyTank() {
        if (!hero.Shots.isEmpty())
            for (int j = 0; j < hero.Shots.size(); j++) {
                Shot shot = hero.Shots.get(j);
                if (shot != null && shot.isLive) {//if (hero.shot.isLive)在未射出前不能访问，会报错
                    for (int i = 0; i < enemyTanks.size(); i++) {
                        EnemyTank enemyTank = enemyTanks.get(i);
                        hitTank(shot, enemyTank);
                    }
                }
            }
    }

    public void hitHeroTank() throws InterruptedException {
        if (!enemyTanks.isEmpty())
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                for (int j = 0; j < enemyTank.Shots.size(); j++) {
                    Shot shot = enemyTank.Shots.get(j);
                    if (hero.isLive && shot.isLive) {
                        if (hitTank(shot, hero)) {
                            Thread.sleep(Constant.REFRESH_RATE*5);
                            beginFlag = false;
                            refreshGame();
                        }
                    }
                }
            }
    }

    @Override
    public void keyPressed(KeyEvent e) {//按下触发

        if (e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP) {
            hero.setDirect(0);
            if (hero.getY() - 30 > 0)
                hero.moveUp();
        } else if (e.getKeyCode() == KeyEvent.VK_D || e.getKeyCode() == KeyEvent.VK_RIGHT) {
            hero.setDirect(1);
            if (hero.getX() + 30 < Constant.GAME_WIDTH)
                hero.moveRight();
        } else if (e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN) {
            hero.setDirect(2);
            if (hero.getY() + 67 < Constant.GAME_HEIGHT)
                hero.moveDown();
        } else if (e.getKeyCode() == KeyEvent.VK_A || e.getKeyCode() == KeyEvent.VK_LEFT) {
            hero.setDirect(3);
            if (hero.getX() - 30 > 0)
                hero.moveLeft();
        }
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            hero.shoot();
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE && !beginFlag)
            begin();
    }

    @Override
    public void run() {//作为主线程对全局的对象进行刷新
        while (true) {
            try {
                Thread.sleep(Constant.REFRESH_RATE);
                hitEnemyTank();
                hitHeroTank();//每一帧都要检查是否碰撞
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            this.repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {//松开触发

    }

    @Override
    public void keyTyped(KeyEvent e) {//字符输出触发

    }
}
